package com.upay.android.controller.fragment;

import static com.upay.android.controller.helper.Keys.TOKEN;
import static com.upay.android.controller.helper.Keys.UPAY_PREFERENCES;
import static com.upay.android.controller.helper.Keys.USERID;
import static com.upay.android.controller.helper.Results.AUTHENTICATED;

import java.util.HashMap;
import java.util.Map;

import org.codehaus.jackson.type.TypeReference;

import android.app.Activity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Loader;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.upay.android.R;
import com.upay.android.controller.helper.Keys;
import com.upay.android.controller.validation.EmailValidator;
import com.upay.android.controller.validation.PasswordValidator;
import com.upay.android.core.service.RestService;
import com.upay.android.domain.authentication.AuthenticationToken;
import com.upay.android.domain.authentication.Credentials;
import com.upay.android.domain.request.RequestBody;
import com.upay.android.domain.request.RequestEnvelope;
import com.upay.android.domain.request.RequestHeader;
import com.upay.android.domain.response.ResponseEnvelope;
import com.upay.android.domain.rest.RestRequest;
import com.upay.android.util.rest.UrlHelper;


public class AuthenticateFragment extends AbstractFragment implements LoaderCallbacks<ResponseEnvelope<AuthenticationToken>> {
	
	/* ---- Constants ---- */
	public static final int AUTHENTICATE = 1;
	
	/* ---- Instance Variables ---- */
	
	private EditText mUserIdField = null;
	private EditText mPasswordField = null;
	private Button mSignInButton = null;
	private TextView mJoinText = null;
	
	private EmailValidator mEmailValidator = null;
	private PasswordValidator mPasswordValidator = null;
	
    private OnJoinUPaySelectedListener mCallback;

	/* ---- Constructors ---- */
	
	/* ---- Business Methods ---- */
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mEmailValidator = new EmailValidator();
        mPasswordValidator = new PasswordValidator(); 
        setRetainInstance(true);
    }
    
    @Override
    public void onStart() {
    	super.onStart();
   		getContext().setTitle(R.string.signin_fragment_title);    	
    }
    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_authenticate, parent, false);
        
        
        
        mUserIdField = (EditText)view.findViewById(R.id.value_signin_userid);
        mPasswordField = (EditText)view.findViewById(R.id.value_signin_password);
        mSignInButton = (Button)view.findViewById(R.id.button_signin);
        mJoinText = (TextView)view.findViewById(R.id.label_signin_join);
        
        mSignInButton.setOnClickListener(new View.OnClickListener() {		
			@Override
			public void onClick(View view) {
		    	
				// Retrieve credentials
		        String userId = mUserIdField.getText().toString();
		        String password = mPasswordField.getText().toString();

		        // Validate credentials
		        Map<String, String> errors = new HashMap<String, String>();
		        mEmailValidator.validate(userId, errors);
		        mPasswordValidator.validate(password, errors);
		        
		        if (errors.size() > 0) {
		        	getContext().showValidationErrors(
		        		getContext().getApplicationContext().getResources().getString(R.string.authenticate_invalid_credentials),
		        		Gravity.CENTER);
		        } else  {
	           	    Bundle bundle = new Bundle();
	           	    bundle.putString(Keys.USERID, userId);
	           	    bundle.putString(Keys.PASSWORD, password);           	    
	           	    getLoaderManager().initLoader(AUTHENTICATE, bundle, AuthenticateFragment.this);
	           	    
		        }
			}
		});     
        
        mJoinText.setOnClickListener(new View.OnClickListener() {
	
			@Override
			public void onClick(View view) {
				mCallback.onJoinSelected();		
			}
		});
        return view; 
    }
       
    
    /* ---- Interfaces ---- */
    
	@Override
	public Loader<ResponseEnvelope<AuthenticationToken>> onCreateLoader(int id, Bundle bundle) {  	    
   	    Credentials credentials = new Credentials(bundle.getString(Keys.USERID), bundle.getString(Keys.PASSWORD));
   	    RequestEnvelope<RequestHeader, Credentials> requestEnvelope = new RequestEnvelope<RequestHeader, Credentials>(
   	    	new RequestHeader(),
   	    	new RequestBody<Credentials>(credentials));
   	    TypeReference<ResponseEnvelope<AuthenticationToken>> typeReference = new TypeReference<ResponseEnvelope<AuthenticationToken>>() {};
   	    RestRequest<RequestHeader, Credentials, AuthenticationToken> restRequest = new RestRequest<RequestHeader, Credentials, AuthenticationToken>(
   	    	UrlHelper.getUrl(getResources(), UrlHelper.AUTHENTICATE),
   	    	requestEnvelope,
   	    	typeReference);           	    
   	    RestService<RequestHeader, Credentials, AuthenticationToken> restService = new RestService<RequestHeader, Credentials, AuthenticationToken>(
   	    	getActivity().getApplicationContext(),
   	    	restRequest);
   	    return restService;
	}

	@Override
	public void onLoadFinished(Loader<ResponseEnvelope<AuthenticationToken>> loader, ResponseEnvelope<AuthenticationToken> response) {
		if (!response.getResponseHeader().getStatus()) {
			getContext().handleError(response.getResponseBody().getResponseError());
		} else {
			AuthenticationToken authenticationToken = response.getResponseBody().getResponseObject();
		
			// Save Credentials
			SharedPreferences sharedPreferences = getContext().getSharedPreferences(UPAY_PREFERENCES, 0);
			SharedPreferences.Editor editor = sharedPreferences.edit();
			editor.putString(USERID, authenticationToken.getUserName());
			editor.putString(TOKEN, authenticationToken.getToken());
			editor.commit();
        
			// Return to Activity
			getContext().setResult(AUTHENTICATED, getContext().getIntent());
			getContext().finish();
		}
	}

	@Override
	public void onLoaderReset(Loader<ResponseEnvelope<AuthenticationToken>> arg0) {
	}  
    
    // Container Activity must implement this interface
    public interface OnJoinUPaySelectedListener {
        public void onJoinSelected();
    }
    
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnJoinUPaySelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnJoinUPaySelectedListener");
        }
    }


    
}
